--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/android_push_bridge.py e41daa5b65e07a5baa1aaad32d97f90482f1cd1c (e41daa5b) Text, 7.67 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Android (Chaquopy): mirror selected websocket payloads to OS notifications."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787json
Tff7b72import T7ee787logging
Tff7b72from T7ee787typing Tff7b72import Te6edf3Any
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787lxmf_utils Tff7b72import Te6edf3is_user_facing_lxmf_payload
Te6edf3logger Tff7b72= Te6edf3loggingTff7b72.Td2a8ffgetLoggerTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.android_push_bridgeTa5d6ff"Tb4b4b4)
Te6edf3_ws_hook_installed Tff7b72= Tff7b72False
Tff7b72def Td2a8ff_is_chaquopy_androidTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72import T7ee787java T8b949e# noqa: F401
Tff7b72except Tf85149ImportErrorTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72True
Tff7b72def Td2a8ff_get_android_external_files_dirTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Return the Android app-specific external files directory, or None.
This path is user-accessible via file managers (Android/data/<pkg>/files).
"""
Tff7b72if Tff7b72not Te6edf3_is_chaquopy_androidTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787comT7ee787.T7ee787chaquoT7ee787.T7ee787python Tff7b72import Te6edf3Python
Te6edf3context Tff7b72= Te6edf3PythonTff7b72.Td2a8ffgetPlatformTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffgetApplicationTb4b4b4(Tb4b4b4)
Te6edf3external Tff7b72= Te6edf3contextTff7b72.Td2a8ffgetExternalFilesDirTb4b4b4(Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3external Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72return Tffa657strTb4b4b4(Te6edf3externalTff7b72.Td2a8ffgetAbsolutePathTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_android_notification_bridgeTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787comT7ee787.T7ee787meshchatx Tff7b72import Tb4b4b4(
Te6edf3AndroidNotificationBridgeTb4b4b4, T8b949e# type: ignore[import-not-found,import-untyped]
Tb4b4b4)
Tff7b72return Te6edf3AndroidNotificationBridge
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffAndroid notification bridge unavailable: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_dnd_enabledTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Te6edf3bridgeTff7b72.Td2a8ffisDoNotDisturbEnabledTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72def Td2a8ff_is_open_conversationTb4b4b4(Te6edf3destination_hashTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72if Tff7b72not Te6edf3destination_hashTb4b4b4:
Tff7b72return Tff7b72False
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Te6edf3bridgeTff7b72.Td2a8ffisOpenConversationHashTb4b4b4(Te6edf3destination_hashTb4b4b4)Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72def Td2a8fflxmf_delivery_notification_textTb4b4b4(Te6edf3payloadTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Return (title, body) for a system notification, or None to skip."""
Tff7b72if Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4) Tff7b72!= Ta5d6ff"Ta5d6fflxmf.deliveryTa5d6ff"Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsieve_suppress_notificationsTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3msg Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflxmf_messageTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3msgTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3is_user_facing_lxmf_payloadTb4b4b4(
Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3source_hash Tff7b72= Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3source_hashTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3_is_open_conversationTb4b4b4(Te6edf3source_hashTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Te6edf3_dnd_enabledTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3sender Tff7b72= Tffa657strTb4b4b4(Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_identity_nameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffMeshTa5d6ff"
Te6edf3title Tff7b72= Tffa657strTb4b4b4(Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3content Tff7b72= Tffa657strTb4b4b4(Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3contentTb4b4b4) Tff7b72> T79c0ff200Tb4b4b4:
Te6edf3content Tff7b72= Te6edf3contentTb4b4b4[Tb4b4b4:T79c0ff197Tb4b4b4] Tff7b72+ Ta5d6ff"Ta5d6ff...Ta5d6ff"
Tff7b72if Te6edf3title Tff7b72and Te6edf3contentTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3titleTffd700}Tffea00\nTffd700{Te6edf3contentTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3titleTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Te6edf3titleTb4b4b4)
Tff7b72if Te6edf3contentTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Te6edf3contentTb4b4b4)
Te6edf3fields Tff7b72= Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimageTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Ta5d6ff"Ta5d6ffImage messageTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffaudioTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Ta5d6ff"Ta5d6ffAudio messageTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3fieldsTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3fieldsTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffile_attachmentsTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Ta5d6ff"Ta5d6ffAttachmentTa5d6ff"Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3senderTb4b4b4, Ta5d6ff"Ta5d6ffNew messageTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ff_notify_javaTb4b4b4(
Te6edf3titleTb4b4b4: Tffa657strTb4b4b4,
Te6edf3bodyTb4b4b4: Tffa657strTb4b4b4,
Te6edf3dedupe_hexTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Te6edf3destination_hashTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3bridgeTff7b72.Td2a8ffshowInboundMessageTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3dedupe_hexTb4b4b4, Te6edf3destination_hashTb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4:
T8b949e# Older bridge signature without destination hash.
Tff7b72tryTb4b4b4:
Te6edf3bridgeTff7b72.Td2a8ffshowInboundMessageTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3dedupe_hexTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffshowInboundMessage failed: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffshowInboundMessage failed: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72def Td2a8ff_notify_incoming_call_javaTb4b4b4(Te6edf3caller_nameTb4b4b4: Tffa657strTb4b4b4, Te6edf3dedupe_hexTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3bridgeTff7b72.Td2a8ffshowIncomingCallTb4b4b4(Te6edf3caller_nameTb4b4b4, Te6edf3dedupe_hexTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffshowIncomingCall failed: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72def Td2a8ff_notify_missed_call_javaTb4b4b4(Te6edf3titleTb4b4b4: Tffa657strTb4b4b4, Te6edf3bodyTb4b4b4: Tffa657strTb4b4b4, Te6edf3dedupe_hexTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3bridgeTff7b72.Td2a8ffshowMissedCallTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3dedupe_hexTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffshowMissedCall failed: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72def Td2a8ff_cancel_incoming_call_notification_javaTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3bridge Tff7b72= Te6edf3_android_notification_bridgeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bridge Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3bridgeTff7b72.Td2a8ffcancelIncomingCallNotificationTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffcancelIncomingCallNotification failed: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72def Td2a8ff_after_websocket_broadcastTb4b4b4(Te6edf3dataTb4b4b4: Tffa657objectTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72except Te6edf3jsonTff7b72.Td2a8ffJSONDecodeErrorTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3payloadTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return
Te6edf3t Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3t Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6fftelephone_call_endedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftelephone_call_establishedTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3_cancel_incoming_call_notification_javaTb4b4b4(Tb4b4b4)
Tff7b72return
Tff7b72if Te6edf3t Tff7b72== Ta5d6ff"Ta5d6fftelephone_ringingTa5d6ff"Tb4b4b4:
Tff7b72if Te6edf3_dnd_enabledTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return
Te6edf3ch Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_identity_hashTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72= Tb4b4b4(Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_identity_nameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffMeshTa5d6ff"
Te6edf3ded Tff7b72= Te6edf3ch Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3chTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3chTb4b4b4) Tff7b72>Tff7b72= T79c0ff8 Tff7b72else Tff7b72None
Te6edf3_notify_incoming_call_javaTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3dedTb4b4b4)
Tff7b72return
Tff7b72if Te6edf3t Tff7b72== Ta5d6ff"Ta5d6fftelephone_missed_callTa5d6ff"Tb4b4b4:
Tff7b72if Te6edf3_dnd_enabledTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return
Te6edf3sender Tff7b72= Tb4b4b4(Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_identity_nameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffMeshTa5d6ff"
Te6edf3ch Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_identity_hashTa5d6ff"Tb4b4b4)
Te6edf3h Tff7b72= Te6edf3ch Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3chTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3chTb4b4b4) Tff7b72>Tff7b72= T79c0ff8 Tff7b72else Tff7b72None
Tff7b72if Te6edf3sender Tff7b72and Te6edf3sender Tff7b72!= Ta5d6ff"Ta5d6ffMeshTa5d6ff"Tb4b4b4:
Te6edf3title Tff7b72= Ta5d6ff"Ta5d6ffMissed callTa5d6ff"
Te6edf3body Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffMissed call from Tffd700{Te6edf3senderTffd700}Ta5d6ff"
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3chTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3chTb4b4b4:
Te6edf3short_h Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3chTb4b4b4[Tb4b4b4:T79c0ff6Tb4b4b4]Tffd700}Ta5d6ff" Tff7b72if Tffa657lenTb4b4b4(Te6edf3chTb4b4b4) Tff7b72> T79c0ff6 Tff7b72else Te6edf3ch
Te6edf3title Tff7b72= Ta5d6ff"Ta5d6ffMissed callTa5d6ff"
Te6edf3body Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffFrom Tffd700{Te6edf3short_hTffd700}Ta5d6ff...Ta5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3title Tff7b72= Ta5d6ff"Ta5d6ffMissed callTa5d6ff"
Te6edf3body Tff7b72= Ta5d6ff"Ta5d6ffMissed callTa5d6ff"
Te6edf3_notify_missed_call_javaTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3hTb4b4b4)
Tff7b72return
Te6edf3pair Tff7b72= Te6edf3lxmf_delivery_notification_textTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72if Tff7b72not Te6edf3pairTb4b4b4:
Tff7b72return
Te6edf3titleTb4b4b4, Te6edf3body Tff7b72= Te6edf3pair
Te6edf3msg Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflxmf_messageTa5d6ff"Tb4b4b4)
Te6edf3dedupe Tff7b72= Tff7b72None
Te6edf3destination_hash Tff7b72= Tff7b72None
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3msgTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3h Tff7b72= Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3hTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3hTb4b4b4) Tff7b72>Tff7b72= T79c0ff8Tb4b4b4:
Te6edf3dedupe Tff7b72= Te6edf3h
Te6edf3src Tff7b72= Te6edf3msgTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3srcTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3srcTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3destination_hash Tff7b72= Te6edf3srcTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3_notify_javaTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3dedupeTb4b4b4, Te6edf3destination_hashTb4b4b4)
Tff7b72def Td2a8ffinstall_websocket_hookTb4b4b4(Te6edf3reticulum_mesh_chat_clsTb4b4b4: Tffa657typeTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72global Te6edf3_ws_hook_installed
Tff7b72if Tff7b72not Te6edf3_is_chaquopy_androidTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72if Te6edf3_ws_hook_installedTb4b4b4:
Tff7b72return
Te6edf3orig Tff7b72= Te6edf3reticulum_mesh_chat_clsTff7b72.Td2a8ffwebsocket_broadcast
Tff7b72async Tff7b72def Td2a8ff_wrappedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Te6edf3result Tff7b72= Tff7b72await Te6edf3origTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3_after_websocket_broadcastTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffandroid ws hook post-broadcast failedTa5d6ff"Tb4b4b4, Te6edf3exc_infoTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72return Te6edf3result
Te6edf3reticulum_mesh_chat_clsTff7b72.Td2a8ffwebsocket_broadcast Tff7b72= Te6edf3_wrapped
Te6edf3_ws_hook_installed Tff7b72= Tff7b72True
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────